/**
 * @file wa_processbar.c
 *
 */

 /*********************
 *      INCLUDES
 *********************/
#include "wa_conf.h"
#if USE_WA_PROCESSBAR != 0
#include "wa_processbar.h"

 /*********************
 *      DEFINES
 *********************/

 /**********************
 *      TYPEDEFS
 **********************/

 /**********************
 *  STATIC PROTOTYPES
 **********************/
static wa_obj_callback ancestor_callback;
static void wa_processbar_callback(wa_sign* sign);
/**********************
 *  STATIC VARIABLES
 **********************/


 /**********************
 *      MACROS
 **********************/

 /**********************
 *   GLOBAL FUNCTIONS
 **********************/
 /**
 * processbar module init
 */
void wa_processbar_module_init(void)
{
}

/**
* create a processbar
* @param par
* @return proccessbar obj
*/
wa_obj* wa_processbar_create(wa_obj* par)
{
	wa_obj* new_processbar;
	wa_processbar_ext* processbar_ext;

	new_processbar = wa_obj_create(par, NULL);
	if (new_processbar == NULL)
	{
		return new_processbar;
	}

	if (ancestor_callback == NULL)
	{
		ancestor_callback = wa_obj_get_callback(new_processbar);
	}
	processbar_ext = wa_obj_malloc_ext_attr(new_processbar, sizeof(wa_processbar_ext));

	processbar_ext->dir = WA_PROCESSBAR_DIR_LEFT;
	processbar_ext->min_value = 0;
	processbar_ext->max_value = 100;
	processbar_ext->value = 50;
	processbar_ext->fore_color = WA_COLOR_FOREGROUND;
	processbar_ext->back_color = WA_COLOR_BACKGROUND;
	processbar_ext->edge_size = 1;
	processbar_ext->interval = 1;

	wa_obj_set_callback(new_processbar, wa_processbar_callback);

	return new_processbar;
}

/**
* processbar set direction
* @param processbar
* @param direction
*/
void wa_processbar_set_direction(wa_obj* processbar, wa_processbar_direction direction)
{
	wa_processbar_ext* ext;
	ext = wa_obj_get_ext_attr(processbar);
	ext->dir = direction;
	wa_obj_invalidate(processbar);
}

/**
* processbar set min and max value
* @param processbar
* @param min
* @param max
*/
void wa_processbar_set_limit_value(wa_obj* processbar, int32_t min, int32_t max)
{
	wa_processbar_ext* ext;
	ext = wa_obj_get_ext_attr(processbar);
	ext->min_value = min;
	ext->max_value = max;
	wa_obj_invalidate((wa_obj*)processbar);
}

/**
* processbar set value
* @param processbar
* @param value
*/
void wa_processbar_set_value(wa_obj* processbar, int32_t value)
{
	wa_processbar_ext* ext;
	ext = wa_obj_get_ext_attr(processbar);
	if (value >= ext->max_value)
	{
		value = ext->max_value;
	}
	if (value <= ext->min_value)
	{
		value = ext->min_value;
	}
	if (value == ext->value)
	{
		return;
	}
	ext->value = value;
	wa_wm_notify_parent(processbar, WA_SIGNAL_NOTIFY_VALUE_CHANGED);
	wa_obj_invalidate(processbar);
}

/**
* processbar fore color
* @param processbar
* @param fore color
*/
void wa_processbar_set_fore_color(wa_obj* processbar, wa_gui_color color)
{
	wa_processbar_ext* ext;
	ext = wa_obj_get_ext_attr(processbar);
	ext->fore_color = color;
	wa_obj_invalidate(processbar);
}

/**
* processbar back color
* @param processbar
* @param back color
*/
void wa_processbar_set_back_color(wa_obj* processbar, wa_gui_color color)
{
	wa_processbar_ext* ext;
	ext = wa_obj_get_ext_attr(processbar);
	ext->back_color = color;
	wa_obj_invalidate(processbar);
}

/**
* processbar edge size
* @param processbar
* @param edge size
*/
void wa_processbar_set_edge_size(wa_obj* processbar, uint32_t edge_size)
{
	wa_processbar_ext* ext;
	ext = wa_obj_get_ext_attr(processbar);
	ext->edge_size = edge_size;
	wa_obj_invalidate(processbar);
}

/**
* processbar interval
* @param processbar
* @param interval
*/
void wa_processbar_set_interval(wa_obj* processbar, uint32_t interval)
{
	wa_processbar_ext* ext;
	ext = wa_obj_get_ext_attr(processbar);
	ext->interval = interval;
	wa_obj_invalidate(processbar);
}

/**
* processbar get direction
* @param processbar
* @return direction
*/
wa_processbar_direction wa_processbar_get_direction(wa_obj* processbar)
{
	wa_processbar_ext* ext;
	ext = wa_obj_get_ext_attr(processbar);
	return ext->dir;
}

/**
* processbar get value
* @param processbar
* @return value
*/
int32_t wa_processbar_get_value(wa_obj* processbar)
{
	wa_processbar_ext* ext;
	ext = wa_obj_get_ext_attr(processbar);
	return ext->value;
}

/**
* processbar get fore color
* @param processbar
* @return fore color
*/
wa_gui_color wa_processbar_get_fore_color(wa_obj* processbar)
{
	wa_processbar_ext* ext;
	ext = wa_obj_get_ext_attr(processbar);
	return ext->fore_color;
}

/**
* processbar get back color
* @param processbar
* @return back color
*/
wa_gui_color wa_processbar_get_back_color(wa_obj* processbar)
{
	wa_processbar_ext* ext;
	ext = wa_obj_get_ext_attr(processbar);
	return ext->back_color;
}

/**
* processbar get edge size
* @param processbar
* @return edge size
*/
uint32_t wa_processbar_get_edge_size(wa_obj* processbar)
{
	wa_processbar_ext* ext;
	ext = wa_obj_get_ext_attr(processbar);
	return ext->edge_size;
}

/**
* processbar get interval
* @param processbar
* @return edge interval
*/
uint32_t wa_processbar_get_interval(wa_obj* processbar)
{
	wa_processbar_ext* ext;
	ext = wa_obj_get_ext_attr(processbar);
	return ext->interval;
}

/**********************
*   STATIC FUNCTIONS
**********************/
/**
* processbar redraw functions
* @param obj
*/
static void _Paint(wa_obj* obj)
{
	uint32_t i;
	int32_t x, y, w, h;
	wa_processbar_ext* ext;
	ext = wa_obj_get_ext_attr(obj);

	wa_mask_fillrect(obj->rect.x1, obj->rect.y1,
		wa_obj_get_width(obj),
		wa_obj_get_height(obj),
		&(obj->redraw_rect),
		ext->back_color);

	for (i = 0; i < ext->edge_size; i++)
	{
		wa_mask_drawrect(obj->rect.x1 + i, obj->rect.y1 + i,
						wa_obj_get_width(obj) - 2 * i,
						wa_obj_get_height(obj) - 2 * i,
						&(obj->redraw_rect),
						ext->fore_color);
	}

	if (ext->dir == WA_PROCESSBAR_DIR_DOWN)
	{
		w = wa_obj_get_width(obj) - 2 * ext->edge_size - 2 * ext->interval;
		h = (ext->value - ext->min_value) * (wa_obj_get_height(obj) - 2 * ext->edge_size - 2 * ext->interval) / (ext->max_value - ext->min_value);
		x = obj->rect.x1 + ext->edge_size + ext->interval;
		y = obj->rect.y1 + ext->edge_size + ext->interval + wa_obj_get_height(obj) - 2 * ext->edge_size - 2 * ext->interval - h;
		wa_mask_fillrect(x, y, w, h, &(obj->redraw_rect), ext->fore_color);
	}
	else if (ext->dir == WA_PROCESSBAR_DIR_UP)
	{
		x = obj->rect.x1 + ext->edge_size + ext->interval;
		y = obj->rect.y1 + ext->edge_size + ext->interval;
		w = wa_obj_get_width(obj) - 2 * ext->edge_size - 2 * ext->interval;
		h = (ext->value - ext->min_value) * (wa_obj_get_height(obj) - 2 * ext->edge_size - 2 * ext->interval)/(ext->max_value - ext->min_value);
		wa_mask_fillrect(x, y, w, h, &(obj->redraw_rect), ext->fore_color);
	}
	else if (ext->dir == WA_PROCESSBAR_DIR_LEFT)
	{
		x = obj->rect.x1 + ext->edge_size + ext->interval;
		y = obj->rect.y1 + ext->edge_size + ext->interval;
		w = (ext->value - ext->min_value) * (wa_obj_get_width(obj) - 2 * ext->edge_size - 2 * ext->interval) / (ext->max_value - ext->min_value);
		h = wa_obj_get_height(obj) - 2 * ext->edge_size - 2 * ext->interval;
		wa_mask_fillrect(x, y, w, h, &(obj->redraw_rect), ext->fore_color);
	}
	else if (ext->dir == WA_PROCESSBAR_DIR_RIGHT)
	{
		w = (ext->value - ext->min_value) * (wa_obj_get_width(obj) - 2 * ext->edge_size - 2 * ext->interval) / (ext->max_value - ext->min_value);
		h = wa_obj_get_height(obj) - 2 * ext->edge_size - 2 * ext->interval;
		x = obj->rect.x1 + ext->edge_size + ext->interval + wa_obj_get_width(obj) - 2 * ext->edge_size - 2 * ext->interval - w;
		y = obj->rect.y1 + ext->edge_size + ext->interval;
		wa_mask_fillrect(x, y, w, h, &(obj->redraw_rect), ext->fore_color);
	}
}

/**
 * processbar obj delete function
 * @param obj
 */
static void _Delete(wa_obj* obj)
{
}

/**
 * processbar obj callback function
 * @param sign
 */
static void wa_processbar_callback(wa_sign* sign)
{
	int sign_id;
	wa_obj* obj;

	ancestor_callback(sign);
	sign_id = sign->sign_id;
	obj = sign->obj_dst;

	switch (sign_id)
	{
		case WA_SIGNAL_PAINT:
		{
			_Paint(obj);
			break;
		}
		case WA_SIGNAL_DELETE:
		{
			_Delete(obj);
			break;
		}
		default:
		{
			break;
		}
	}
}

#endif
